package control;
import java.util.Vector;

import storage.ManageData;
import utils.CommandAnalyzer;
import utils.CommandGenerator;
import domain.Expense;
import domain.Income;
import domain.Loan;
import enums.Frequency;
import enums.LoanState;

import basic.CRUDable;
import basic.Date;
import basic.Manager;

//@author A0103947A
public class LoanManager extends Manager  {
	
	private Vector<Loan> _listOfLoans;
	private MemberManager _memMan;
//	private CategoryManager _catMan;
//	private PaymentMethodManager _payMan;
	private ExpenseManager _expenseMan;
	private IncomeManager _incomeMan;
	private double _totalAmountBorrowed;
	private double _totalAmountLent;

	
	/**
	 * @param budget
	 * @param memMan
	 */
	public LoanManager(MemberManager memMan, CategoryManager catMan, PaymentMethodManager payMan, ExpenseManager expenseMan, IncomeManager incomeMan)
	{
		_expenseMan = expenseMan;
		_incomeMan = incomeMan;
		this.initialize(); 
		_memMan = memMan;
//		_catMan = catMan;
//		_payMan = payMan;
	}
	/**
	 * 
	 * @return _listOfLoans
	 * @Precondition 
	 * @Postcondition 
	 */
	public Vector<Loan> getList()
	{
		return this._listOfLoans;
	}
	
	/**
	 * 
	 * @param loanManager
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set(LoanManager loanManager)
	{
		super.set(loanManager);
		this._listOfLoans = loanManager._listOfLoans;
	}
	
	/**
	 *
	 * @see basic.Manager#add(basic.CRUDable)
	 * @param item
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	@Override
	public int add(CRUDable item) {
		item.set_id(_nextId++);
		if(this._listOfLoans.add((Loan)item))
		{
			((Loan)item).set_lastUpdateDate(((Loan)item).get_date());
			checkRecurLoan((Loan)item);
			if(((Loan)item).get_loanState()==LoanState.LENT)
			{
				_totalAmountLent += ((Loan)item).get_amount();
			}
			else if(((Loan)item).get_loanState()==LoanState.BORROWED)
			{
				_totalAmountBorrowed += ((Loan)item).get_amount();
			}
			return item.get_id();
		}
		else
		{
			_nextId--;
			return -1;
		}
	}

	/**
	 *
	 * @see basic.Manager#addTo(basic.CRUDable, int, int)
	 * @param item
	 * @param id
	 * @param pos
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	@Override
	public boolean addTo(CRUDable item, int id,int pos) {
		item.set_id(id);
		((Loan)item).set_lastUpdateDate(((Loan)item).get_date());
		checkRecurLoan((Loan)item);
		if(((Loan)item).get_loanState()==LoanState.LENT)
		{
			_totalAmountLent += ((Loan)item).get_amount();
		}
		else if(((Loan)item).get_loanState()==LoanState.BORROWED)
		{
			_totalAmountBorrowed += ((Loan)item).get_amount();
		}
		this._listOfLoans.add(pos,(Loan)item);
		return true;
	}

	/**
	 *
	 * @see basic.Manager#get(int)
	 * @param id
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	@Override
	public Loan get(int id) {
		for(Loan l:_listOfLoans)
		{
			if(l.get_id()==id)
				return l;
		}
		return null;
	}

	/**
	 *
	 * @see basic.Manager#edit(int, basic.CRUDable)
	 * @param id
	 * @param item
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	@Override
	public Loan edit(int id, CRUDable item) {
		for(Loan l: _listOfLoans)
		{
			if(l.get_id()==id)
			{
				Loan loan = new Loan(l);

				if(l.get_loanState()==LoanState.BORROWED)
				{
					_expenseMan.deleteLoans(l.get_name(), l.get_paymentPerMonth(), l.get_date());
					
				}
				
				l.set((Loan)item);//this casting is necessary
				l.set_lastUpdateDate(l.get_date());
				checkRecurLoan(l);
				
				if(((Loan)item).get_loanState()==LoanState.LENT
						&&loan.get_loanState()==LoanState.LENT)
				{
					_totalAmountLent -= loan.get_amount();
					_totalAmountLent += l.get_amount();
				}//the new item is lent but old one is borrowed
				else if(((Loan)item).get_loanState()==LoanState.LENT)
				{
					_totalAmountBorrowed -= loan.get_amount();
					_totalAmountLent += l.get_amount();
				}//the new item is borrow but the old is lent
				else if(loan.get_loanState()==LoanState.LENT)
				{
					_totalAmountLent -= loan.get_amount();
					_totalAmountBorrowed += l.get_amount();
				}
				else//both borrow
				{
					_totalAmountBorrowed -= loan.get_amount();
					_totalAmountBorrowed += l.get_amount();
				}
	
				return loan;
			}
		}
		return null;
	}

	/**
	 *
	 * @see basic.Manager#delete(int)
	 * @param id
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	@Override
	public Loan delete(int id) {
		for(Loan l:_listOfLoans)
		{
			if(l.get_id()==id)
			{
				if(_listOfLoans.remove(l))
				{
					// If "BORROWED" or "LENT",
					// _expenseMan.deleteLoans(String name, monthly payment, start date); OR
					// _incomeMan.deleteLoans(String name, monthly payment, start date);
					if(l.get_loanState()==LoanState.LENT)
					{
						_totalAmountLent -= l.get_amount();
					}
					else if(l.get_loanState()==LoanState.BORROWED)
					{
						_totalAmountBorrowed -= l.get_amount();
						//deleteLoanExpenses(l, _expenseIDList);
						_expenseMan.deleteLoans(l.get_name(), l.get_paymentPerMonth(), l.get_date());
						
					}
					else if (l.get_loanState() == LoanState.BORROWED_CLEARED) {
						_expenseMan.deleteLoans(l.get_name(), l.get_paymentPerMonth(), l.get_date());
					}
					else if (l.get_loanState() == LoanState.LENT_CLEARED) {
						_incomeMan.deleteLentInterest(l.get_name(), l.get_gainFromInterest(), l.get_date());
					}
					else if (l.get_loanState() == LoanState.INVESTMENT_CLEARED) {
						_incomeMan.deleteInvestmentInterest(l.get_name(), l.get_gainFromInterest(),  l.get_date());
					}
					return l;
				}
				else
					return null;
			}
		}
		return null;
	}
	
	public int deleteFrom(int id) {
		int i=0;
		for(Loan l:_listOfLoans)
		{
			if(l.get_id()==id)
			{
				if(_listOfLoans.remove(l))
				{
					if(l.get_loanState()==LoanState.LENT)
					{
						_totalAmountLent -= l.get_amount();
					}
					else if(l.get_loanState()==LoanState.BORROWED)
					{
						_totalAmountBorrowed -= l.get_amount();
						_expenseMan.deleteLoans(l.get_name(), l.get_paymentPerMonth(), l.get_date());
					}
					else if (l.get_loanState() == LoanState.BORROWED_CLEARED) {
						_expenseMan.deleteLoans(l.get_name(), l.get_paymentPerMonth(), l.get_date());
					}
					else if (l.get_loanState() == LoanState.LENT_CLEARED) {
						_incomeMan.deleteLentInterest(l.get_name(), l.get_gainFromInterest(),  l.get_date());
					}
					else if (l.get_loanState() == LoanState.INVESTMENT_CLEARED) {
						_incomeMan.deleteInvestmentInterest(l.get_name(), l.get_gainFromInterest(), l.get_date());
					}
					return i;
				}
				else
					return -1;
			}
			i++;
		}
		return -1;
	}

	//@author a0098891H
	/**
	 *
	 * @see interfaces.CommandLine#readCmd(java.lang.String)
	 * @param cmd
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	@Override
	public int readCmd(String cmd) {
		//<LOAN>|<ADD> <NAME> <AMOUNT> <LOANSTATE> (COMPULSORY)
		//<LOAN>|<EDIT> <ID> <NAME> <AMOUNT> <LOANSTATE>(COMPULSORY) 
		//OPTIONAL BUT NEED PARAMETER <DUEDATE> <DATE> <MEMBER> <COMMENTS> <Interest> <year>
		
		//<LOAN>|<DELETE> <ID>
		//<LOAN>|<VIEW> <ID>
		//<LOAN>|<UNDO>
		//check undo
		boolean isUndo = false;
		boolean isRedo = false;
		
		if(cmd.trim().compareToIgnoreCase("undo")==0)
		{
			if(!_undoStack.isEmpty())
			{
				isUndo = true;
				cmd = _undoStack.pop();
				int iAction = cmd.indexOf('[');
				int isavedId = cmd.indexOf('&');
				int isavedPos = cmd.indexOf(']');
				_undoAction = Integer.parseInt(cmd.substring(0, iAction));
				_savedId = Integer.parseInt(cmd.substring(iAction+1, isavedId));
				_savedPos = Integer.parseInt(cmd.substring(isavedId+1, isavedPos));

				if(_undoAction==ACTION_DELETE || _undoAction==ACTION_EDIT)
				{
					_redoStack.add(cmd.substring(0,cmd.indexOf('|')));
					cmd = cmd.substring(cmd.indexOf('|')+1);
				}
			}
		}
		else if(cmd.trim().compareToIgnoreCase("redo")==0)
		{
			if(!_redoStack.isEmpty())
			{
				isRedo = true;
				cmd = _redoStack.pop();
				if(cmd.indexOf(']')!=-1)
				{
					int iAction = cmd.indexOf('[');
					int isavedId = cmd.indexOf('&');
					int isavedPos = cmd.indexOf(']');
					_undoAction = Integer.parseInt(cmd.substring(0, iAction));
					_savedId = Integer.parseInt(cmd.substring(iAction+1, isavedId));
					_savedPos = Integer.parseInt(cmd.substring(isavedId+1, isavedPos));
					cmd = cmd.substring(cmd.indexOf(']')+1);
				}
			}	
		}
		
		String str[] = cmd.split(",");
		for(int i=0;i<str.length;i++)
		{
			str[i] = str[i].trim();
		}
		int length = str.length;
		if(length < 2)
			return -1;

		switch(str[1].toLowerCase())
		{
		case "add":
			if(length < 5) 
				return -1;
			Loan loan = new Loan();
			if(str[2].trim().isEmpty())
				return -1;
			loan.set_name(str[2]);
			try{
			loan.set_amount(Double.parseDouble(str[3]));
//				loan.set_totalAmount(Double.parseDouble(str[3]));
			}
			catch(NumberFormatException e)
			{
				return -1;
			}
			switch(str[4].toLowerCase())
			{
			case "borrow":
			case "borrowed":
				loan.set_loanState(LoanState.BORROWED);
				break;
			case "lend":
			case "lent":
				loan.set_loanState(LoanState.LENT);
				break;
			case "investment":
			case "invest":
				loan.set_loanState(LoanState.INVESTMENT);
				break;
			case "cleared":
				loan.set_loanState(LoanState.BORROWED_CLEARED);
				break;
			default:
				return -1;
			}
			loan.set_dueDate(CommandAnalyzer.getDueDate(str));
			if(!CommandAnalyzer.validateDateForLoanNInvestment(str))
				return -1;
			loan.set_date(CommandAnalyzer.getDate(str));
			loan.set_monthsRemaining(loan.get_date(), loan.get_dueDate());	
			loan.set_interestRate(CommandAnalyzer.getInterest(str));
			loan.updateTotalAmount();
			loan.set_gainFromInterest(loan.get_totalAmount() - loan.get_amount());
			loan.set_paymentPerMonth();
			loan.set_partyInvolved(CommandAnalyzer.getPartyInvolved(str));
			loan.set_byMem(_memMan.get(CommandAnalyzer.getMemberID(str)));
			loan.set_comments(CommandAnalyzer.getComments(str));
			loan.set_interestRate(CommandAnalyzer.getInterest(str));
			loan.set_lastUpdateDate(CommandAnalyzer.getUpdateDate(str));


			_returnedObject = loan;
			if(isUndo && _undoAction==ACTION_ADD)
			{
				int _savedPos = deleteFrom(_savedId);
				if(_savedPos >= 0)
				{//must record the position and id for redo
					_redoStack.add(-1+"["+_savedId+"&"+_savedPos+"]"+cmd);
					return _undoAction;
				}
				else
					return -1;//undo failed
			}
			if(isUndo && _undoAction==ACTION_DELETE)
			{
				if(loan.get_loanState() == LoanState.BORROWED_CLEARED || loan.get_loanState() == LoanState.LENT_CLEARED
					|| loan.get_loanState() == LoanState.INVESTMENT_CLEARED) {
					return -1;
				}
				if(!addTo(loan,_savedId,_savedPos))
					return -1;
				return _undoAction;
			}

			if(isRedo)
			{
				if(!addTo(loan,_savedId,_savedPos))
					return -1;
			}
			else
			{
				_savedId = add(loan);
			}
			if(_savedId<0)
				return -1;
			_action = ACTION_ADD;
			break;
		case "delete":
			if(length < 3)
				return -1;
			try{
				_savedId = Integer.parseInt(str[2]);
				Loan deletedLoan = get(_savedId);
				if(deletedLoan==null)
					return -1;
				_savedPos = this._listOfLoans.indexOf(deletedLoan);
				deletedLoan = delete(_savedId);
				if(deletedLoan==null)
					return -1;
				_returnedObject = deletedLoan;
				cmd+="|loan,add,"+deletedLoan.toString();
				_action = ACTION_DELETE;
			}
			catch(NumberFormatException e)
			{
				return -1;
			}
			
			
			break;
		case "edit":
			if(length < 5)
				return -1;
			try{
				
				_savedId = Integer.parseInt(str[2]);
				Loan updatedLoan = new Loan();
				if(str[3].trim().isEmpty())
					return -1;
				updatedLoan.set_name(str[3]);
				updatedLoan.set_amount(Double.parseDouble(str[4]));
				switch(str[5].toLowerCase())
				{
				case "borrow":
				case "borrowed":
					updatedLoan.set_loanState(LoanState.BORROWED);
					break;
				case "lend":
				case "lent":
					updatedLoan.set_loanState(LoanState.LENT);
					break;
				case "investment":
				case "invest":
					updatedLoan.set_loanState(LoanState.INVESTMENT);
					break;
				case "cleared":
					updatedLoan.set_loanState(LoanState.BORROWED_CLEARED);
					break;
				default:
					return -1;
				}

				updatedLoan.set_dueDate(CommandAnalyzer.getDueDate(str));
				if(!CommandAnalyzer.validateDateForLoanNInvestment(str))
					return -1;
				updatedLoan.set_date(CommandAnalyzer.getDate(str));
				updatedLoan.set_monthsRemaining(updatedLoan.get_date(), updatedLoan.get_dueDate());
				updatedLoan.set_interestRate(CommandAnalyzer.getInterest(str));
				updatedLoan.updateTotalAmount();
				updatedLoan.set_gainFromInterest(updatedLoan.get_totalAmount() - updatedLoan.get_amount());
				updatedLoan.set_paymentPerMonth();
				updatedLoan.set_partyInvolved(CommandAnalyzer.getPartyInvolved(str));
				updatedLoan.set_byMem(_memMan.get(CommandAnalyzer.getMemberID(str)));
				updatedLoan.set_comments(CommandAnalyzer.getComments(str));
				updatedLoan.set_interestRate(CommandAnalyzer.getInterest(str));
				updatedLoan.set_lastUpdateDate(CommandAnalyzer.getUpdateDate(str));
				//updatedLoan.set_totalAmount(CommandAnalyzer.getTotalAmount(str));

				Loan obsoleteLoan = edit(_savedId,updatedLoan);

				if(obsoleteLoan==null)
					return -1;

				_returnedObject = obsoleteLoan;
				if(isUndo && _undoAction==ACTION_EDIT)
				{
//					this._listOfLoans.get(_savedId).set_totalAmount(updatedLoan.get_totalAmount());
//					this._listOfLoans.get(_savedId).set_lastUpdateDate(updatedLoan.get_date());
					return _undoAction;
				}
				cmd+="|loan,edit,"+_savedId+","+obsoleteLoan.toString();
				_action = ACTION_EDIT;
			}
			catch(NumberFormatException e)
			{
				return -1;
			}
			break;
		default:
			return -1;
		}

		_undoStack.add(_action+"["+ _savedId +"&"+ _savedPos +"]"+cmd);
		return _action;
	}

	/**
	 *
	 * @see basic.Manager#alize()
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	@Override
	public boolean initialize() {
		if(loadAll()==false)
		{
			super.initialize();
			this._listOfLoans = new Vector<Loan>();
			_totalAmountBorrowed = 0;
			_totalAmountLent = 0;
		}
		checkAllRecurLoans();
		return true;
	}
	
	/**
	 *
	 * @param loan
	 * @return true
	 * @Precondition loan may or may not be updated to current date (with monthly expected payments for borrowed/lent
	 * 	 			 and annual increase in interest for investment
	 * @Postcondition updates loan up to the current date
	 */

	public boolean checkRecurLoan(Loan loan)
	{	//TODO
			switch(loan.get_frequency()) {
			case NO:
				loan.set_totalAmount(loan.get_amount());
				break;
			case MONTHLY:
				doMonthlyCheck(loan);
				break;
			default:
				return false;
			}
		return true;
	}

	//@author a0103947A
	/**
	 *
	 * @param
	 * @return true
	 * @Precondition loans may or may not be updated to the current date; may not be the case if application is opened for the first time
	 * 				 in a long time
	 * @Postcondition updates all loans up to the current date
	 */
	public boolean checkAllRecurLoans()
	{	//TODO
		Vector<Loan> tempVector = new Vector <Loan> (_listOfLoans);
		for (Loan loan: tempVector) {
			 checkRecurLoan(loan);
		}
		
		return true;
	}
	
	
	/**
	 *
	 * @param loan
	 * @return
	 * @Precondition 
	 * @Postcondition loan is updated each month up to current date with appropriate deductions from monthsLeft and additions to expenses/income
	 */
	private void doMonthlyCheck(Loan loan) {
		// TODO Auto-generated method stub	
		
		// Check dueDate with curDate, if dueDate has already passed, set curDate to dueDate
		Date dueDate = loan.get_dueDate();
		int dueYear = dueDate.get_year();
		int dueMonth = dueDate.get_month();
		int dueDay = dueDate.get_day();
		
		Date curDate = Date.getCurrentDate();
		int curYear = curDate.get_year();
		int curMonth = curDate.get_month();
		int curDay = curDate.get_day();
		
		if (dueYear < curYear || (dueYear == curYear && dueMonth <= curMonth && dueDay <= curDay)) {
			curDate = dueDate;
			curYear = dueYear;
			curMonth = dueMonth;
			curDay = dueDay;
		}
		
		// Get temporary values for day, month, and year representing the last update date
		int tempYear = loan.get_lastUpdateDate().get_year();
		int tempMonth = loan.get_lastUpdateDate().get_month();
		int tempDay= loan.get_lastUpdateDate().get_day();
	
		
		// Increment _lastUpdateDate by 1
		if (tempMonth == 12) {
			tempMonth = 1;
			tempYear += 1;
		}
		else {
			tempMonth++;
		}
		
		// If tempYear is less than curYear or tempYear is equal to curYear AND curMonth <= tempMonth
		// AND tempDay <= curDay
		while((tempYear < curYear || (tempYear == curYear && tempMonth <= curMonth) ||
		(tempYear == curYear && tempMonth == curMonth && tempDay <= curDay)) && (loan.get_loanState() != LoanState.BORROWED_CLEARED
		|| loan.get_loanState() != LoanState.LENT_CLEARED || loan.get_loanState() != LoanState.INVESTMENT_CLEARED))
		{
			// Set new _lastUpdateDate
			Date newDate = new Date(tempDay, tempMonth, tempYear);
			loan.set_lastUpdateDate(newDate);
			
			// Decrement monthsLeft by 1, decrement _amount by _paymentPerMonth
			int newMonthsLeft = loan.get_monthsLeft() - 1;
			double newAmountRemaining = loan.get_totalAmount() - loan.get_paymentPerMonth();
			loan.set_monthsLeft(newMonthsLeft);
			loan.set_totalAmount(newAmountRemaining);
			
			// Add loan to expense
			if (loan.get_loanState() == LoanState.BORROWED) {
				Expense xpnToAdd = new Expense();
				xpnToAdd.set_name(loan.get_name() + " Loan");
				xpnToAdd.set_amount(loan.get_paymentPerMonth());
				xpnToAdd.set_partyInvolved(loan.get_partyInvolved());
				xpnToAdd.set_byMem(loan.get_byMem());
				xpnToAdd.set_frequency(Frequency.NO);
				xpnToAdd.set_category(1);
				xpnToAdd.set_date(loan.get_date());
				
				_expenseMan.add(xpnToAdd);
			}
			
			else if (loan.get_loanState() == LoanState.INVESTMENT) {
				// Compare curYear and curMonth with start date's year and month,
				// If curYear > startYear and curMonth == startMonth OR investment
				// Is about to end (_monthsLeft == 0), then add interest to _amount
				Date startDate = loan.get_date();
				int startYear = startDate.get_year();
				int startMonth = startDate.get_month();
				
				if (loan.get_monthsLeft() == 0 || (tempYear > startYear && tempMonth == startMonth)) {
					loan.set_totalAmount(loan.get_totalAmount() * (1 + loan.get_interestRate()/100));
					//System.out.println("FromInterest occurs in incrementation every year for investment in checkRecurLoan");
					loan.set_gainFromInterest(loan.get_totalAmount()-loan.get_amount());
				}
			}
			
			// If _monthsleft == 0, delete it from _listOfLoans
			// If item deleted is an investment, add investment to income
			if (loan.get_monthsLeft() == 0) {
				
				if (loan.get_loanState() == LoanState.BORROWED) {
					loan.set_loanState(LoanState.BORROWED_CLEARED);
				}
				else if (loan.get_loanState() == LoanState.LENT) {
					if(loan.get_gainFromInterest() > 0) {
						Income incomeToAdd = new Income();
						incomeToAdd.set_name(loan.get_name() + " Lent Interest");
						incomeToAdd.set_amount(loan.get_gainFromInterest());
						incomeToAdd.set_byMem(loan.get_byMem());
						incomeToAdd.set_partyInvolved(loan.get_partyInvolved());
						incomeToAdd.set_frequency(Frequency.NO);
						incomeToAdd.set_date(loan.get_date());
						
						_incomeMan.add(incomeToAdd);
					}
					
					loan.set_loanState(LoanState.LENT_CLEARED);
				}
				else if (loan.get_loanState() == LoanState.INVESTMENT) {	
					if(loan.get_gainFromInterest() > 0) {
						Income incomeToAdd = new Income();
						incomeToAdd.set_name(loan.get_name() + " Investment Interest");
						incomeToAdd.set_amount(loan.get_gainFromInterest());
						incomeToAdd.set_byMem(loan.get_byMem());
						incomeToAdd.set_partyInvolved(loan.get_partyInvolved());
						incomeToAdd.set_frequency(Frequency.NO);
						incomeToAdd.set_date(loan.get_date());
						
						_incomeMan.add(incomeToAdd);
					}
					
					loan.set_loanState(LoanState.INVESTMENT_CLEARED);
				}
				loan.set_totalAmount(0);
				//loan.set_gainFromInterest(0);
				

			}

			
			// Increment _lastUpdateDate by 1
			if (tempMonth == 12) {
				tempMonth = 1;
				tempYear += 1;
			}
			else {
				tempMonth++;
			}
		}
	}
	
	public void deleteLoanExpenses(Loan l, Vector<Integer> _listOfExpenseIDs) {
		_expenseMan.deleteLoans(l.get_name(), l.get_paymentPerMonth(), l.get_date());
	}
	
	/**
	 *
	 * @see basic.Manager#saveAll()
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	@Override
	public boolean saveAll() {
		return ManageData.saveLoanManagerToFile(this);
	}

	/**
	 *
	 * @see basic.Manager#loadAll()
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	@Override
	public boolean loadAll() {
		LoanManager loanManager = ManageData.loadLoanManagerFromFile();
		if(loanManager==null)
		{
			return false;
		}
		this.set(loanManager);
		return true;
	}
	

	/**
	 *
	 * @see java.lang.Object#toString()
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public String toString()
	{
		StringBuilder sb = new StringBuilder();
		for(Loan loan : this._listOfLoans)
		{
			sb.append("  ("+loan.get_id()+") "+loan.toString() + "\n");
		}
		sb.append("total lent: "+this._totalAmountLent +"\n");
		sb.append("total owned: "+this._totalAmountBorrowed +"\n");
		return sb.toString();
	}

	public double get_totalAmountBorrowed() {
		return _totalAmountBorrowed;
	}

	public double get_totalAmountLent() {
		return _totalAmountLent;
	}
	/**
	 * 
	 * @return returns number of total loans
	 * @Precondition 
	 * @Postcondition 
	 */
	public int get_totalLoans() {
		int count = 0;
		
		for (Loan currLoan: _listOfLoans) {
			if (currLoan.get_loanState() == LoanState.BORROWED || currLoan.get_loanState() == LoanState.LENT)
				count++;
		}
		
		return count;
	}
	
	/**
	 * 
	 * @return returns number of borrowed loans
	 * @Precondition 
	 * @Postcondition 
	 */
	public int get_totalLoansBorrowed() {
		int count = 0;
		for (Loan currLoan: _listOfLoans) {
			if (currLoan.get_loanState() == LoanState.BORROWED) 
				count++;
		}
		
		return count;
	}
	
	/**
	 * 
	 * @return returns total interest from borrowed loans
	 * @Precondition 
	 * @Postcondition 
	 */
	public double get_totalInterestLostFromBorrowed() {
		double amount = 0;
		
		for (Loan currLoan: _listOfLoans) {
			if (currLoan.get_loanState() == LoanState.BORROWED) {
				
				amount += currLoan.get_gainFromInterest();
			}
		}
		
		return amount;
	}
	
	/**
	 * 
	 * @return returns total amount from lent loans
	 * @Precondition 
	 * @Postcondition 
	 */
	public double get_amountFromLoansLent() {
		double amount = 0;
		
		for (Loan currLoan: _listOfLoans) {
			if (currLoan.get_loanState() == LoanState.LENT) {
				
				amount += currLoan.get_amount();
			}
		}
		
		return amount;
	}
	
	/**
	 * 
	 * @return returns number of loans lent
	 * @Precondition 
	 * @Postcondition 
	 */
	public int get_totalLoansLent() {
		int count = 0;
		for (Loan currLoan: _listOfLoans) {
			if (currLoan.get_loanState() == LoanState.LENT) 
				count++;
		}
		
		return count;
	}
	
	/**
	 * 
	 * @return returns total interest to be gained (sums up all gains from interest for lent loans)
	 * @Precondition 
	 * @Postcondition 
	 */
	public double get_totalInterestToBeGained() {
		double amount = 0;
		
		for (Loan currLoan: _listOfLoans) {
			if (currLoan.get_loanState() == LoanState.LENT) {
				
				amount += currLoan.get_gainFromInterest();

			}
		}
		
		return amount;
	}
	
	/**
	 * 
	 * @return returns totoal monthly payment for borrowed loans
	 * @Precondition 
	 * @Postcondition 
	 */
	public double get_monthlyPaymentForBorrowed() {
		double amount = 0;
		for (Loan currLoan: _listOfLoans) {
			if (currLoan.get_loanState() == LoanState.BORROWED && currLoan.get_monthsLeft() > 0)
				amount += currLoan.get_paymentPerMonth();
		}
		
		return amount;
	}
	
	/**
	 * 
	 * @return returns monthly total gained for lent
	 * @Precondition 
	 * @Postcondition 
	 */
	public double get_monthlyCollectionForRent() {
		double amount = 0;
		for (Loan currLoan: _listOfLoans) {
			if (currLoan.get_loanState() == LoanState.LENT && currLoan.get_monthsLeft() > 0)
				amount += currLoan.get_paymentPerMonth();
		}
		
		return amount;
	}
	
	/**
	 * 
	 * @return returns total number of investments
	 * @Precondition 
	 * @Postcondition 
	 */
	public int numberOfInvestments() {
		int count = 0;
		for (Loan currLoan: _listOfLoans) {
			if (currLoan.get_loanState() == LoanState.INVESTMENT && currLoan.get_monthsLeft() > 0)
				count++;
		}
		
		return count;
	}
	
	/**
	 * 
	 * @return returns total value from investments
	 * @Precondition 
	 * @Postcondition 
	 */
	public double get_valueInvested() {
		double value = 0;
		for(Loan currLoan: _listOfLoans) {
			if (currLoan.get_loanState() == LoanState.INVESTMENT && currLoan.get_monthsLeft() > 0)
				value += currLoan.get_amount();
		}
		
		return value;
	}

	/**
	 * 
	 * @return returns sizes of _listOfLoans
	 * @Precondition 
	 * @Postcondition 
	 */
	public int size() {
		return this._listOfLoans.size();
	}
	
	/**
	 * 
	 * @return returns total amount from loans and investments
	 * @Precondition 
	 * @Postcondition 
	 */
	public double getAmountOut()
	{
		double amount = 0;
		for(Loan loan:this._listOfLoans)
		{
			if(loan.get_loanState()==LoanState.INVESTMENT||loan.get_loanState()==LoanState.LENT)
			{
				amount+=loan.get_amount();
			}
		}
		return amount;
	}
	

	/**
	 * 
	 * @return returns total amount from loans and investments
	 * @Precondition 
	 * @Postcondition 
	 */
	public int getTotalClearedLoans() {
		int count = 0;
		
		for (Loan loan: this._listOfLoans) {
			if (loan.get_loanState()==LoanState.BORROWED_CLEARED||loan.get_loanState()==LoanState.LENT_CLEARED
					|| loan.get_loanState() == LoanState.INVESTMENT_CLEARED) {
				count++;
			}
		}
		
		return count;
	}
}
